#include <stdlib.h>
#include <stdio.h>
#include "tga.h"

#include "../file.h"

bool
e3dLoadTGA (eFile& file, TGAFILE* tgaFile)
{
  if (! file.size ())
    return false;

  unsigned char Unused000;  // 1 byte of garbage
  short int     Unused001;  // 2 bytes of garbage
  long          imageSize;  // Size of TGA image
  int           colorMode;  // 4 == RGBA, 3 == RGB
  long          imageIndex; // Index ID
  unsigned char colorSwap;  // Swap buffer

  // Read first two bytes of garbage.
  file.read (&Unused000, sizeof (unsigned char), 1);
  file.read (&Unused000, sizeof (unsigned char), 1);

  // Read the image type
  file.read (&tgaFile->imageTypeCode, sizeof (unsigned char), 1);

  // Make sure we're not trying to load an RLE Targa image!
  if ((tgaFile->imageTypeCode != 2) && (tgaFile->imageTypeCode != 3))
  {
//    fclose (fTGA);
    return false;
  }


  // Read 13 more bytes of garbage
  file.read (&Unused001, sizeof (short int),     1);
  file.read (&Unused001, sizeof (short int),     1);
  file.read (&Unused000, sizeof (unsigned char), 1);
  file.read (&Unused001, sizeof (short int),     1);
  file.read (&Unused001, sizeof (short int),     1);

  // Read image dimensions
  file.read (&tgaFile->imageWidth,  sizeof (short int), 1);
  file.read (&tgaFile->imageHeight, sizeof (short int), 1);


  // Read image bit-depth
  file.read (&tgaFile->bitCount, sizeof (unsigned char), 1);

  // Read 1 byte of garbage
  file.read (&Unused000, sizeof (unsigned char), 1);

  // colorMode -> 3 == BGR,  4 == BGRA
  colorMode = tgaFile->bitCount / 8;
  imageSize = tgaFile->imageWidth * tgaFile->imageHeight * colorMode;

  tgaFile->numChannels = colorMode;

  // Allocate memory for image data
  tgaFile->imageData = (unsigned char*) malloc (sizeof (unsigned char) * imageSize);

  // Read the image data
  file.read (tgaFile->imageData, sizeof (unsigned char), imageSize);

  // Change BGR to RGB so OpenGL can use the texture
  for (imageIndex = 0; imageIndex < imageSize; imageIndex += colorMode)
  {
    colorSwap = tgaFile->imageData [imageIndex];
    tgaFile->imageData [imageIndex]     = tgaFile->imageData [imageIndex + 2];
    tgaFile->imageData [imageIndex + 2] = colorSwap;
  }

  /// XXX: Temp Hack: Transparent alpha channels equate to full-bright rgb.
  if (colorMode > 3) {
    for (imageIndex = 0; imageIndex < imageSize; imageIndex += colorMode)
    {
      if (tgaFile->imageData [imageIndex +3] == 0) {
        tgaFile->imageData [imageIndex] = 0xff;
	tgaFile->imageData [imageIndex + 1] = 0xff;
	tgaFile->imageData [imageIndex + 2] = 0xff;
      }
    }
  }

  // Close the file
//  fclose (fTGA);

  return true;

}

bool
e3dLoadTGAFile (char* filename, TGAFILE* tgaFile)
{
  FILE*         fTGA;       // File pointer
  unsigned char Unused000;  // 1 byte of garbage
  short int     Unused001;  // 2 bytes of garbage
  long          imageSize;  // Size of TGA image
  int           colorMode;  // 4 == RGBA, 3 == RGB
  long          imageIndex; // Index ID
  unsigned char colorSwap;  // Swap buffer

  // Open the file
  if (! (fTGA = fopen (filename, "rbS")))
    return false;

  // Read first two bytes of garbage.
  fread (&Unused000, sizeof (unsigned char), 1, fTGA);
  fread (&Unused000, sizeof (unsigned char), 1, fTGA);

  // Read the image type
  fread (&tgaFile->imageTypeCode, sizeof (unsigned char), 1, fTGA);

  // Make sure we're not trying to load an RLE Targa image!
  if ((tgaFile->imageTypeCode != 2) && (tgaFile->imageTypeCode != 3))
  {
    fclose (fTGA);
    return false;
  }


  // Read 13 more bytes of garbage
  fread (&Unused001, sizeof (short int),     1, fTGA);
  fread (&Unused001, sizeof (short int),     1, fTGA);
  fread (&Unused000, sizeof (unsigned char), 1, fTGA);
  fread (&Unused001, sizeof (short int),     1, fTGA);
  fread (&Unused001, sizeof (short int),     1, fTGA);

  // Read image dimensions
  fread (&tgaFile->imageWidth,  sizeof (short int), 1, fTGA);
  fread (&tgaFile->imageHeight, sizeof (short int), 1, fTGA);


  // Read image bit-depth
  fread (&tgaFile->bitCount, sizeof (unsigned char), 1, fTGA);

  // Read 1 byte of garbage
  fread (&Unused000, sizeof (unsigned char), 1, fTGA);

  // colorMode -> 3 == BGR,  4 == BGRA
  colorMode = tgaFile->bitCount / 8;
  imageSize = tgaFile->imageWidth * tgaFile->imageHeight * colorMode;

  // Allocate memory for image data
  tgaFile->imageData = (unsigned char*) malloc (sizeof (unsigned char) * imageSize);

  // Read the image data
  fread (tgaFile->imageData, sizeof (unsigned char), imageSize, fTGA);

  // Change BGR to RGB so OpenGL can use the texture
  for (imageIndex = 0; imageIndex < imageSize; imageIndex += colorMode)
  {
    colorSwap = tgaFile->imageData [imageIndex];
    tgaFile->imageData [imageIndex]     = tgaFile->imageData [imageIndex + 2];
    tgaFile->imageData [imageIndex + 2] = colorSwap;
  }

  // Close the file
  fclose (fTGA);

  return true;
}


bool
l3dSaveTGAFile ( const char*          filename,
                 const short int&     width,
                 const short int&     height,
                 const unsigned char& bits,
                 unsigned char* imageData )
{
  unsigned char Unused000;  // Garbage collector (1-byte)
  short int     Unused001;  // Garbage collector (2-bytes)
  unsigned char imageType;  // Type of image we're writing
  int           colorMode;  // Color mode
  unsigned char colorSwap;  // Swap buffer
  int           imageIndex; // Index ID
  unsigned char bitDepth;   // Bit depth
  long          imageSize;  // Image data size
  FILE*         fTGA;       // Image file

  // Create our image
  if (! (fTGA = fopen (filename, "wbS")))
  {
    fclose (fTGA);
    return false;
  }

  switch (bits) {
    case 32:
      imageType = 3;  /* RGBA (BGRA) - Uncompressed */
      bitDepth  = 32;
      colorMode = 4;  /* 32-Bit RGBA */
      break;
    default:
    case 24:
      imageType = 2;  /* RGB (BGR) - Uncompressed */
      bitDepth  = 24;
      colorMode = 3;  /* 24-Bit RGB */
      break;
    case 16:
      imageType = 2;  /* RGB (BGR) - Uncompressed */
      bitDepth  = 16;
      colorMode = 2;  /* 16-Bit RGB */
      break;
  }

  Unused000 = NULL; // Garbage!
  Unused001 = NULL; // Garbage!

  // Write garbage (No Extra Header, No Compression)
  fwrite (&Unused000, sizeof (unsigned char),  1, fTGA);
  fwrite (&Unused000, sizeof (unsigned char),  1, fTGA);

  // Write imageType
  fwrite (&imageType, sizeof (unsigned char),  1, fTGA);

  // Write more garbage (No Compression)
  fwrite (&Unused001, sizeof (short int),      1, fTGA);
  fwrite (&Unused001, sizeof (short int),      1, fTGA);
  fwrite (&Unused000, sizeof (unsigned char),  1, fTGA);
  fwrite (&Unused001, sizeof (short int),      1, fTGA);
  fwrite (&Unused001, sizeof (short int),      1, fTGA);

  // Write image dimensions
  fwrite (&width,    sizeof (short int),       1, fTGA);
  fwrite (&height,   sizeof (short int),       1, fTGA);
  fwrite (&bitDepth, sizeof (unsigned char),   1, fTGA);

  // Write more garbage (No Flags)
  fwrite (&Unused000, sizeof (unsigned char),  1, fTGA);

  // Calculate image size
  imageSize = width * height * colorMode;

  // Change image data from RGB to BGR
  for (imageIndex = 0; imageIndex < imageSize; imageIndex += colorMode)
  {
    colorSwap = imageData [imageIndex];
    imageData [imageIndex]     = imageData [imageIndex + 2];
    imageData [imageIndex + 2] = colorSwap;
  }

  // Write the image data
  fwrite (imageData, sizeof (unsigned char), imageSize, fTGA);

  // Close the file
  fclose (fTGA);

  return true;
}

